#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

struct udp_data
{
    short command = 0;   // 0 stand break and exit
    char data[50];
};


#define BUFSIZE 100

int main(){
    int server_sock;
    int len;

    struct sockaddr_in my_addr;
    struct sockaddr_in remote_addr;

    int sin_size;
    char buff[BUFSIZ]{0};
    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    my_addr.sin_port = htons(55555);

    // create socket
    if (0 > (server_sock = socket(PF_INET, SOCK_DGRAM, 0))){
        perror("socket cannot be created!");
        return -1;
    }

    if (0 > bind(server_sock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))){
        perror("bind failed!");
        return -1;
    }

    sin_size = sizeof(sockaddr_in);
    std::cout << "waiting for packet ... ..." << std::endl;

    udp_data data;
    data.command = 0;
    strcpy(data.data, "holle");
    while(true){
        if (0 > recvfrom(server_sock, buff, BUFSIZ, 0, (struct sockaddr *)&remote_addr, (socklen_t *)&sin_size)){
            perror("recive error once ...");
            continue;
        }

        std::cout << "received packet from " << inet_ntoa(remote_addr.sin_addr) << std::endl;
        memcpy(&data, buff, sizeof(data));
        std::cout << "command received : " << data.command << std::endl;
        std::cout << "message received : " << data.data << std::endl;

        if(0 == data.command){
            std::cout << "server exit" << std::endl;
            data.command = 0;
            strcpy(data.data, "server exit done.");
            memcpy(buff, &data, sizeof(data));
            sendto(server_sock, buff, strlen(buff), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
            break;
        }else{
            std::cout << "return command : " << data.command << std::endl;
            std::cout << "lucky " << std::endl;
            std::cout << std::endl;
            memcpy(buff, &data, sizeof(data));
            sendto(server_sock, buff, strlen(buff), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));

        }
        std::cout << std::endl;
    }
    close(server_sock);

    return 0;
}